#include "stdafx.h"
#include "LitTokeniser.h"

namespace Lit
{
	Tokeniser::Tokeniser( ){ }
	Tokeniser::Tokeniser( const String &str, const String &delim ){ if( !str.empty() ) vec = str.split(delim); }
	Tokeniser::Tokeniser( const Tokeniser& rk ){ vec=rk.vec; }
	Tokeniser::~Tokeniser( ){}

	String Tokeniser::join( const String &link ) const
	{
		String ret;
		for( size_t i=0;
			i<vec.size();
			i++ )
		{
			ret += vec.at(i) +link;
		}
		ret.trim();
		return ret;
	}
		
	Tokeniser& Tokeniser::operator=( const Tokeniser& rk ){ vec=rk.vec; return *this; }
	Tokeniser& Tokeniser::operator+=( const Tokeniser& rk ){ for( size_t i=0; i<rk.vec.size(); i++ ) vec.push_back( String(rk.vec.at(i)) ); return *this; }
	Tokeniser Tokeniser::operator+( const Tokeniser& rk ) const{ Tokeniser tok; for( size_t i=0; i<rk.vec.size(); i++ ) tok.vec.push_back( String(rk.vec.at(i)) ); return tok; }

	String Tokeniser::argAt( size_t id )
	{
		if( vec.empty() ) throw MissingParameter( "arg("+String(std::to_string(id).c_str())+")", EXC_LOC );
		if( id >= vec.size() ) throw std::range_error( (String(std::to_string(id).c_str()) + " not in range [0," + std::to_string(vec.size()).c_str() + "]").data() );
		return vec.at(id);
	}
	String Tokeniser::nextArg(){
		if( vec.empty() ) throw MissingParameter( "nextArg", EXC_LOC );
		String a( vec.at(0) );
		vec.erase( 0 );
		return a;
	}
	Tokeniser& Tokeniser::eat( size_t num ){
		vec = Tokeniser( rest( num ) ).vec;
		return *this;
	}
	Tokeniser Tokeniser::eat( size_t num ) const
	{
		return Tokeniser( rest( num ) );
	}
	bool Tokeniser::hasMimimum(size_t num_args_required ) const
	{
		return count() >= num_args_required;
	}

	bool Tokeniser::hasMoreArgs( size_t from ) const
	{
		return from < count();
	}

	String Tokeniser::rest( size_t from_arg ) const
	{
		String ret;
		if( from_arg>=count() ) 
			throw std::range_error( "no arguments left" );
		for( size_t i=from_arg; i<count(); i++ )
			ret += vec.at(i) + " ";
		return ret.trimmed();
	}
	size_t Tokeniser::count() const{ return vec.size(); }
	bool Tokeniser::empty() const{ return vec.empty(); }
};